<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            font-size: 1vmin;
        }

        body {
            display: flex;
            position: relative;
            justify-content: center;
            align-items: center;
            width: 100%;
            height: 100dvh;
            background-color: #171717;
            /* overflow: hidden; */
        }

        .asciibox {
            font-size: 0.3rem;
            color: #17f700;
            line-height: 0.4rem;
            letter-spacing: 0.1rem;
            white-space: pre;
            font-family: 'Courier New', monospace;
        }
    </style>
</head>

<body>
    <pre class="asciibox"></pre>
</body>

<script type="module">
    import { parseGIF, decompressFrames } from "https://cdn.jsdelivr.net/npm/gifuct-js@2.1.2/+esm";

    const asciiChars = ' .:-=+*#%@';
    const asciiElement = document.querySelector('.asciibox');
    let frames = [];
    let currentFrame = 0;

    const asciibox = {
        init() {
            fetch("ascii.gif")
                .then((resp) => resp.arrayBuffer())
                .then((buff) => {
                    const gif = parseGIF(buff);
                    this.width = gif.lsd.width;
                    this.height = gif.lsd.height;
                    const decompressedFrames = decompressFrames(gif, true);

                    decompressedFrames.forEach(frame => {
                        const canvas = document.createElement("canvas");
                        const ctx = canvas.getContext("2d");
                        canvas.width = frame.dims.width;
                        canvas.height = frame.dims.height;
                        const image_data = new ImageData(
                            frame.patch,
                            frame.dims.width,
                            frame.dims.height
                        );
                        ctx.putImageData(image_data, 0, 0);

                        // 转换为ASCII
                        const asciiFrame = this.convertToAscii(canvas, frame.dims.width, frame.dims.height);
                        frames.push(asciiFrame);
                    });

                    // 开始播放动画
                    this.playAnimation();
                })
                .catch(err => {
                    console.error('加载GIF失败:', err);
                    asciiElement.textContent = '无法加载ascii.gif文件，请确保文件存在于当前目录';
                });
        },

        convertToAscii(canvas, width, height) {
            const ctx = canvas.getContext('2d');
            const imageData = ctx.getImageData(0, 0, width, height);
            const data = imageData.data;
            let ascii = '';

            for (let y = 0; y < height; y += 2) { // 每隔一行采样以保持比例
                for (let x = 0; x < width; x += 1) {
                    const i = (y * width + x) * 4;
                    const r = data[i];
                    const g = data[i + 1];
                    const b = data[i + 2];
                    const alpha = data[i + 3];

                    if (alpha === 0) {
                        ascii += ' ';
                    } else {
                        // 计算亮度
                        const brightness = (r * 0.299 + g * 0.587 + b * 0.114) / 255;
                        const charIndex = Math.floor(brightness * (asciiChars.length - 1));
                        ascii += asciiChars[charIndex];
                    }
                }
                ascii += '\n';
            }
            return ascii;
        },

        playAnimation() {
            if (frames.length === 0) return;

            const animate = () => {
                asciiElement.textContent = frames[currentFrame];
                currentFrame = (currentFrame + 1) % frames.length;
                setTimeout(animate, 100); // 100ms间隔
            };
            animate();
        }
    };

    // 启动应用
    asciibox.init(); 
</script>

</html>